﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TelnetRouterApplication.Model
{
    public class SettingsModel
    {
        private string _version;
        public string Version
        {
            get { return _version; }
            set { _version = value; }
        }

        private string _hostname;
        public string Hostname
        {
            get { return _hostname; }
            set { _hostname = value; }
        }

        private List<Interface> _interfaces;
        public List<Interface> Interfaces
        {
            get { return _interfaces; }
            set { _interfaces = value; }
        }

        private string _enablePassword;
        public string EnablePassword
        {
            get { return _enablePassword; }
            set { _enablePassword = value; }
        }

        private string _password;
        public string Password
        {
            get { return _password; }
            set { _password = value; }
        }

        private string _clock;
        public string Clock
        {
            get { return _clock; }
            set { _clock = value; }
        }

        //Essa propriedade é para o tempo que vai aparecer no campo com máscara
        private string _maskedClock;
        public string MaskedClock
        {
            get { return _maskedClock; }
            set { _maskedClock = value; }
        }

        private List<Route> _routes;
        public List<Route> Routes
        {
            get
            {
                if (_routes == null)
                {
                    _routes = new List<Route>();
                }
                return _routes;
            }
            set { _routes = value; }
        }

        private List<IpModel> _routesRip;
        public List<IpModel> RoutesRip
        {
            get
            {
                if (_routesRip == null)
                {
                    _routesRip = new List<IpModel>();
                }
                return _routesRip;
            }
            set { _routesRip = value; }
        }

        private bool _isRouter;
        public bool IsRouter
        {
            get { return _isRouter; }
            set { _isRouter = value; }
        }

        public SettingsModel(string version, string hostname)
        {
            this.Version = version;
            this.Hostname = hostname;

            Interfaces = new List<Interface>();
        }

        public SettingsModel(List<string> settingsList)
        {

            Interfaces = new List<Interface>();
            fill(settingsList);
        }

        private void fill(List<string> settingsList)
        {
            IsRouter = true;
            for (int i = 0; i < settingsList.Count; i++)
            {
                //Verifica se a linha contém "version" escrito
                if (settingsList[i].Contains("version"))
                {
                    string[] parameters = settingsList[i].Split(' ');
                    int position = parameters.Length - 1;

                    //Passa o valor da versão, que fica na posição 2 do vetor, para a variável do objeto
                    Version = parameters[position];
                }

                if (settingsList[i].Contains("hostname"))
                {
                    //Adiciona só o nome do host
                    string[] parameters = settingsList[i].Split(' ');
                    int position = parameters.Length - 1;
                    Hostname = parameters[position];
                }

                if (settingsList[i].Contains("enable password"))
                {
                    //Deve vir no formato 'enable password cisco'
                    string[] parameters = settingsList[i].Split(' ');
                    int position = parameters.Length - 1;
                    EnablePassword = parameters[position];
                }

                if (settingsList[i].Contains("line vty 0 4"))
                {
                    if (settingsList[i + 1].Contains("password"))
                    {
                        string[] parameters = settingsList[i+1].Split(' ');
                        int position = parameters.Length - 1;
                        Password = parameters[position];
                    }
                }

                if (settingsList[i].Contains("interface"))
                {
                    //Adicionar a nova na lista de interfaces
                    string[] parameters = settingsList[i].Split(' ');

                    int position = parameters.Length - 1;

                    string interfaceName = parameters[position];
                    string ipInterface = "";
                    string maskInterface = "";
                    string connectionType = "";
                    bool shutdown = true;

                    if (settingsList[i + 1].Contains("no"))
                    {
                        //Quer dizer que existe a interface, mas não tem ip algum vinculado

                        ipInterface = "no ip address";
                        maskInterface = "no mask";
                    }
                    else
                    {
                        parameters = settingsList[i + 1].Split(' ');

                        //Posição 0: ip address
                        //Posição 1: ip (ex: 192.168.1.1)
                        //Posição 2: mask (ex: 255.255.255.0)

                        if (parameters.Length < 2)
                        {
                            ipInterface = "no ip address";
                            maskInterface = "no mask";
                        }
                        else
                        {
                            ipInterface = parameters[1];
                            maskInterface = parameters[2];
                        }
                    }

                    //TODO precisa verificar essa ordem
                    if (settingsList[i + 2].Contains("shutdown"))
                    {
                        shutdown = true;
                        if (settingsList[i + 3].Contains("speed"))
                        {
                            connectionType = settingsList[i + 3];
                            connectionType = connectionType.Replace("\n ", "");
                        }
                    }
                    else if (settingsList[i + 2].Contains("speed"))
                    {
                        connectionType = settingsList[i + 2];
                        connectionType = connectionType.Replace("\n ", "");
                    }

                    //Instanciando o novo objeto da interface
                    Interface routerInterface = new Interface(interfaceName, ipInterface, maskInterface, shutdown, connectionType);

                    //Adiciona na lista
                    Interfaces.Add(routerInterface);
                }
                if (settingsList[i].Contains("network") && settingsList[i].Contains("."))
                {
                    string[] ipRouteSplitted = settingsList[i].Split(' ');

                    //Posição 0: "" (vazio)
                    //Posição 1: network
                    //Posição 2: ip (ex: 192.168.1.0)
                    RoutesRip.Add(new IpModel(ipRouteSplitted[2]));
                }
                if (settingsList[i].Contains("ip route") && settingsList[i].Contains("."))
                {
                    string[] ipRouteSplitted = settingsList[i].Split(' ');

                    //Posição 0: ip
                    //Posição 1: route
                    //Posição 2: network (ex: 192.168.1.0)
                    //Posição 3: mask (ex: 255.255.255.0)
                    //Posição 4: whereToGo (ex: 20.20.20.2)

                    Route route = new Route();
                    route.Network = new IpModel(ipRouteSplitted[2]);
                    route.Mask = new IpModel(ipRouteSplitted[3]);
                    route.WhereToGo = new IpModel(ipRouteSplitted[4]);

                    Routes.Add(route);
                }
                if (settingsList[i].Contains("vlan"))
                {
                    IsRouter = false;
                }
            }
        }

        public override bool Equals(object obj)
        {
            if (obj is SettingsModel)
            {
                SettingsModel compared = (SettingsModel)obj;

                bool equals = compared.Version.Equals(this.Version) && compared.Hostname.Equals(this.Hostname) && compared.EnablePassword.Equals(this.EnablePassword);

                bool interfacesEquals = true;

                for (int i = 0; i < compared.Interfaces.Count; i++)
                {
                    // x &= y é equivalente a x = x & y
                    interfacesEquals &= compared.Interfaces[i].Equals(this.Interfaces[i]);
                }

                bool routesEquals = true;

                for (int i = 0; i < compared.Routes.Count; i++)
                {
                    // x &= y é equivalente a x = x & y
                    routesEquals &= compared.Routes[i].Equals(this.Routes[i]);
                }

                return equals && interfacesEquals && routesEquals;
            }
            else
            {
                return false;
            }
        }

        //Esse método vai receber o parâmetro de tempo não tratado e retornar em uma string do tipo "dd/mm/aaaa hh:mm"
        public static string ClockToMasked(string clock)
        {
            string maskedClock = "";

            //o clock vem no formato:
            //hh:mm:ss.mss UTC diasemana mês dia ano
            string[] parameters = clock.Split(' ');

            if (parameters.Length > 0 && parameters[0].Length > 4)
            {
                string time = parameters[0]; //hh:mm:ss.mss

                string[] hours = time.Split(':');
                string hour = hours[0];
                string min = hours[1];

                //parâmetro 1 é o UTC
                //parâmetro 2 é o dia da semana

                int month = monthToNumber(parameters[3]);
                string monthString = "";
                if (month < 10)
                {
                    monthString += "0";
                }
                monthString += month;

                int day = int.Parse(parameters[4]);
                string dayString = "";
                if (day < 10)
                {
                    dayString += "0";
                }
                dayString += day;

                int year = int.Parse(parameters[5]);

                maskedClock = dayString + "/" + monthString + "/" + year + " " + hour + ":" + min;
            }
            return maskedClock;
        }

        //clock set 10:50:00 Oct 26 2006  (dentro do enable, clock set "horário no padrão do exemplo ao lado")
        public static string MaskedToClock(string maskedClock)
        {
            string clock = "";

            //O clock vem no formato:
            //dd/mm/aaaa hh:mm

            string[] parameters = maskedClock.Split(' ');

            if (parameters.Length > 0)
            {
                string time = parameters[0]; //dd/mm/aaaa

                string[] date = time.Split('/');

                clock = parameters[1] + ":00 " + numberToMonth(int.Parse(date[1])) + " " + date[0] + " " + date[2];
            }

            return clock;
        }

        private static int monthToNumber(string month)
        {
            switch (month)
            {
                case ("Jan"): return 1;
                case ("Feb"): return 2;
                case ("Mar"): return 3;
                case ("Apr"): return 4;
                case ("May"): return 5;
                case ("Jun"): return 6;
                case ("Jul"): return 7;
                case ("Aug"): return 8;
                case ("Sep"): return 9;
                case ("Oct"): return 10;
                case ("Nov"): return 11;
                case ("Dec"): return 12;
                default: return 0;
            }
        }

        private static string numberToMonth(int month)
        {
            switch (month)
            {
                case (1): return "Jan";
                case (2): return "Feb";
                case (3): return "Mar";
                case (4): return "Apr";
                case (5): return "May";
                case (6): return "Jun";
                case (7): return "Jul";
                case (8): return "Aug";
                case (9): return "Sep";
                case (10): return "Oct";
                case (11): return "Nov";
                case (12): return "Dec";
                default: return "";
            }
        }
    }
}
